package view;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import model.DebateFormat;
import model.MainModel;
import model.Speaker;
import model.SpeakerListModel;
import tools.Translator;
import algo.DistributionAlgorithm;
import algo.MatchingException;

import com.google.inject.BindingAnnotation;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.jidesoft.plaf.LookAndFeelFactory;

public class MainWindow extends JFrame implements ListDataListener {

	@BindingAnnotation
	@Target({ FIELD, PARAMETER, METHOD })
	@Retention(RUNTIME)
	public static @interface NamesRef {

	}

	@BindingAnnotation
	@Target({ FIELD, PARAMETER, METHOD })
	@Retention(RUNTIME)
	public static @interface RoomsRef {

	}
	
	// displays the current count of speakers
	private final JLabel speakerCounter;
	// maintains the current list of speakers
	private final SpeakerListModel speakerListModel;
	// Translator used for translating
	private final Translator tr;
	// shows the result
	private final ResultPane resultPane;
	// used to calculate a speaker distribution for a given debate model
	private final DistributionAlgorithm distributionAlgorithm;
	
	@Inject
	public MainWindow(
//			final @RoomsRef String roomsRef,
//			final @NamesRef String namesRef, 
			final Translator tr,
//			final Configurator config,
			final Provider<SpeakerList> speakerlistProvider,
			final Provider<Speaker> speakerProvider,
			final SpeakerListModel speakerListModel,
			final MainModel model,
			final Provider<ResultPane> resultPaneProvider,
			final DistributionAlgorithm distributionAlgorithm,
			final Set<DebateFormat> formats) {
		
		super(tr.tr("WINDOW_TITLE"));
		
		this.speakerListModel = speakerListModel;
		this.tr = tr;
		this.distributionAlgorithm = distributionAlgorithm;
		
		
//		LookAndFeelFactory.installDefaultLookAndFeelAndExtension();

//		names = config.getProperties(namesRef);
//		rooms = config.getProperties(roomsRef);
		
		GridBagLayout gb = new GridBagLayout();
		setLayout(gb);
		GridBagConstraints constraints = new GridBagConstraints();

		// List
		JScrollPane speakerListScrollPane = new JScrollPane(
				speakerlistProvider.get(),
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		constraints.insets = new Insets(10, 10, 10, 10);
		constraints.gridheight = 2;
		constraints.ipady = 10;
		constraints.ipadx = 280;
		constraints.weightx = .5;
		constraints.weighty = 0;
		constraints.fill = GridBagConstraints.BOTH;
		constraints.anchor = GridBagConstraints.NORTHWEST;

		gb.setConstraints(speakerListScrollPane, constraints);

		
		JButton addNewSpeakerButton = new JButton(tr.tr("NEW_SPEAKER"));
		
		// addNewSpeaker
		addNewSpeakerButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				speakerListModel.addElement(speakerProvider.get());
			}
		});

		// speakerCounter
		speakerCounter = new JLabel();
		speakerListModel.addListDataListener(this);
		
		// startButton
		JButton startButton = new JButton(tr.tr("START_BUTTON"));
		startButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try {
					model.setResult(MainWindow.this.distributionAlgorithm.getResult(speakerListModel.getSpeakers(), model.getSpeakerCounts()));
				} catch (MatchingException e) {
					String message;
					if (e.getRole() != null) {
						message = tr.tr("COULD_NOT_MATCH_ROLE") + tr.tr(e.getRole().getLabel());
					} else if (e.getSpeaker() != null) {
						message = tr.tr("COULD_NOT_MATCH_SPEAKER") + e.getSpeaker().getName();
					} else {
						message = e.getMessage();
					}
					JOptionPane.showMessageDialog(MainWindow.this, message);
				}
			}
		});
		
		
		// buttonArea
		JPanel buttonArea = new JPanel();
		buttonArea.setLayout(new FlowLayout());

		// Debate counters
		for (DebateFormat format : formats) {
			final DebateCountSpinner spinner = new DebateCountSpinner(format,
					model);
			buttonArea.add(new JLabel(tr.tr(format.getLabel() + "_COUNT")));
			buttonArea.add(spinner);
		}

		buttonArea.add(addNewSpeakerButton);
		buttonArea.add(speakerCounter);
		buttonArea.add(startButton);

		constraints.ipadx = constraints.ipady;
		constraints.gridx = 1;
		constraints.gridheight = 1;
		constraints.fill = GridBagConstraints.HORIZONTAL;
		gb.setConstraints(buttonArea, constraints);

		// resultArea
		constraints.gridy = 1;
		constraints.weighty = 1;
		constraints.fill = GridBagConstraints.BOTH;
		resultPane = resultPaneProvider.get();
		gb.setConstraints(resultPane, constraints);

		add(speakerListScrollPane);
		add(buttonArea);
		add(resultPane);

		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				// Write nameCache in file
				// TODO
			}
		});

		setSize(1200, 600);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setLocationByPlatform(true);
		setVisible(true);
	}

	@Override
	public void contentsChanged(ListDataEvent arg0) {
		speakerCounter.setText(speakerListModel.size() + " " + tr.tr("SPEAKERS"));
	}

	@Override
	public void intervalAdded(ListDataEvent arg0) {
		contentsChanged(arg0);
		
	}

	@Override
	public void intervalRemoved(ListDataEvent arg0) {
		contentsChanged(arg0);
	}

}
